/**
 * 
 */
package info.niwota.home.fm;

import info.niwota.home.R;
import instant.openvfs.home.AppHelper;
import instant.openvfs.home.Debug;
import instant.openvfs.home.Preferences;

import java.io.IOException;
import java.net.URI;
import java.util.Date;

import jvs.vfs.FileSystem;
import x.java.io.File;
import android.app.Activity;
import android.app.Dialog;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.provider.MediaStore;
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Toast;

/**
 * @author qiangli
 * 
 */
public abstract class ShellActivity extends Activity {

	private static final String[] DATA_PATH_PROJECTION = new String[] { "_data" };

	private static final int RC_DELETE = 10;

	private static final int RC_LINK = 11;

	private static final int RC_NEWFILE_MENU = 12;

	private static final int RC_NEWFOLDER = 14;

	private static final int RC_RECORD_SOUND = 16;

	private static final int RC_RECORD_VIDEO = 17;

	private static final int RC_RENAME = 18;

	private static final int RC_TAKE_PICTURE = 20;

	private static final int RC_WORD = 21;
	
	private static final int RC_EDIT = 22;

	private static final String V_BASE = "v://";

	private static final String TAG = "ShellActivity";

	private static String parseName(String dp) {
		int idx = dp.lastIndexOf("/");
		if (idx > 0) {
			return dp.substring(idx + 1);
		}
		return dp;
	}

	private File oldfile;

	private File contextFile;

	private String getDataPath(Uri uri) {
		Cursor c = null;
		try {
			c = getContentResolver().query(uri, DATA_PATH_PROJECTION, null,
					null, null);
			if (c != null && c.moveToFirst()) {
				return c.getString(0);
			} else {
				return null;
			}
		} finally {
			if (c != null)
				c.close();
		}
	}

	protected void link(Uri data, File file) {
		try {
			String dp = getDataPath(data);
			if (Debug.DEBUG) {
				Log.d(TAG, "returned data: " + data + " path: " + dp);
			}
			String name = parseName(dp);
			File vf = new File(file, name + File.LINK_EXT);
			vf.link(new URI("file:" + dp), "rw");
		} catch (Exception e) {
			Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT).show();
		}
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		try {
			if (Debug.DEBUG) {
				Log.d(TAG, this + " onActivityResult: requestCode: "
						+ requestCode + " resultCode: " + resultCode +" == " + RESULT_OK + " data: "
						+ data);
			}
			if (resultCode == RESULT_CANCELED) {
				return;
			}
			File file = oldfile;
			//
			Uri uri = (data == null ? null : data.getData());
			if (resultCode == RESULT_OK) {
				switch (requestCode) {
				case RC_EDIT:
					refresh(file);
					break;
				case RC_WORD:
					refresh(file);
					break;
				case RC_RECORD_SOUND:
					link(uri, file);
					refresh(file);
					break;
				case RC_TAKE_PICTURE:
					// Bitmap bitmap = (Bitmap) data.getParcelableExtra("data");
					link(uri, file);
					refresh(file);
					break;
				case RC_RECORD_VIDEO:
					link(uri, file);
					refresh(file);
					break;
				case RC_LINK:
					refresh(file);
					break;
				case RC_NEWFOLDER:
					refresh(file);
					break;
				case RC_NEWFILE_MENU:
					if (perform(data.getAction(), file) == false) {
						return;
					}
					break;
				case RC_DELETE:
					//File p = (File) file.getParentFile();
					refresh(file);
					break;
				case RC_RENAME: {
					File nfile = new File(data.getData().getPath());
					refresh(nfile);
					break;
				}
				default:
					//
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		doFinish();
	}

	protected void doFinish() {
		//
	}

	/**
	 * 
	 * @param cmd
	 * @return true if done otherwise false to leave activity running
	 * @throws IOException
	 */
	protected boolean perform(String cmd, File file) throws IOException {
		if (Debug.DEBUG) {
			Log.d(TAG, "perform: " + cmd +" " + file);
		}
		oldfile = file;
		//
		if (cmd == null) {
			return true;
		} else if (cmd.equals(BinConstant.BIN_EDIT)) {
			startEditActivity(file);
			return false;
		} else if (cmd.equals(BinConstant.BIN_WORD)) {
			startActivityForResult(RC_WORD, WordActivity.class, file);
			return false;
		} else if (cmd.equals(BinConstant.BIN_RECORD)) {
			startRecordActivity();
			return false;
		} else if (cmd.equals(BinConstant.BIN_CAMCORDER)) {
			startCamcorderActivity();
			return false;
		} else if (cmd.equals(BinConstant.BIN_CAMERA)) {
			startCameraActivity();
			return false;
		} else if (cmd.equals(BinConstant.BIN_DELETE)) {
			startActivityForResult(RC_DELETE, DeleteActivity.class, file);
			return false;
		} else if (cmd.equals(BinConstant.BIN_NEWFOLDER)) {
			startActivityForResult(RC_NEWFOLDER, NewFolderActivity.class, file);
			return false;
		} else if (cmd.equals(BinConstant.BIN_RENAME)) {
			startActivityForResult(RC_RENAME, RenameActivity.class, file);
			return false;
		} else if (cmd.equals(BinConstant.BIN_LINK)) {
			startActivityForResult(RC_LINK, LinkActivity.class, file);
			return false;
		} else if (cmd.equals(BinConstant.BIN_NEWMENU)) {
			startActivityForResult(RC_NEWFILE_MENU, NewFileActivity.class, file);
			return false;
		} else if (cmd.equals(BinConstant.BIN_SHORTCUT)) {
			ApplicationUtils.startShortcutActivity(this, file);
			return true;
		} else if (cmd.equals(BinConstant.BIN_VIEWIMAGE)) {
			startViewActivity(file);
			return true;
		} else if (cmd.equals(BinConstant.BIN_VIEWTEXT)) {
			startViewActivity(file);
			return true;
		} else if (cmd.equals(BinConstant.BIN_PLAYAUDIO)) {
			startViewActivity(file);
			return true;
		} else if (cmd.equals(BinConstant.BIN_PLAYVIDEO)) {
			startViewActivity(file);
			return true;
		} else if (cmd.equals(BinConstant.BIN_SEND)) {
			ApplicationUtils.startSendActivity(this, file);
			return true;
		} else if (cmd.equals(BinConstant.BIN_VIEW)) {
			startViewActivity(file);
			return true;
		}
		//
		throw new RuntimeException("Not supported. " + cmd);
	}

	private void startEditActivity(File file) {
		ApplicationUtils.startEditActivity(this, file);
	}

	private void startViewActivity(File file) {
		ApplicationUtils.startViewActivity(this, file);
	}

	protected void refresh(File file) throws Exception {
	}

	protected File readPath() {
		String p = Preferences.getLastPath(this, "/");
		File f = new File(p);
		f = (x.java.io.File) (f.isDirectory() ? f : f.getParentFile());
		if (Debug.DEBUG) {
			Log.d(TAG, "readPath: " + f);
		}
		return f;
	}
	
	protected void savePath(File f) {
		String p = (f == null ? null : f.getPath());
		if (Debug.DEBUG) {
			Log.d(TAG, "savePath file: " + p);
		}
		Preferences.putLastPath(this, p);
	}
	
	private void startActivityForResult(int rc, Class<?> cls, File file) {
		Intent intent = new Intent(this, cls);
		Uri uri = Uri.parse(V_BASE + file.getPath());
		intent.setData(uri);
		startActivityForResult(intent, rc);
	}

	private void startRecordActivity() throws IOException {
		// TODO may break in future version as com.* is not public
		Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
		// android.provider.MediaStore.RECORD_SOUND
		intent.setType("audio/3gpp");
		intent.setClassName("com.android.soundrecorder",
				"com.android.soundrecorder.SoundRecorder");
		startActivityForResult(intent, RC_RECORD_SOUND);
	}

	private void startCamcorderActivity() {
		Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
		intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0);
		startActivityForResult(intent, RC_RECORD_VIDEO);
	}

	private void startCameraActivity() {
		Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
		startActivityForResult(intent, RC_TAKE_PICTURE);
	}

	@Override
	protected void onPrepareDialog(int id, Dialog dialog) {
		switch (id) {
		case Dialogs.DIALOG_PROPERTY: {
			File f = getSelectedFile();
			if (f == null) {
				return; // ignore
			}
			EditText path = (EditText) dialog.findViewById(R.id.property_path);
			path.setText(f.getPath());
			EditText size = (EditText) dialog.findViewById(R.id.property_size);
			size.setText(f.length() + "");
			EditText modified = (EditText) dialog
					.findViewById(R.id.property_modified);
			modified.setText(new Date(f.lastModified()).toLocaleString());
			EditText uri = (EditText) dialog.findViewById(R.id.property_uri);
			uri.setText(f.toRealURI().toString());
			CheckBox read = (CheckBox) dialog
					.findViewById(R.id.property_readable);
			read.setChecked(f.canRead());
			CheckBox write = (CheckBox) dialog
					.findViewById(R.id.property_writable);
			write.setChecked(f.canWrite());
			CheckBox mp = (CheckBox) dialog
					.findViewById(R.id.property_mountpoint);
			mp.setChecked(FileSystem.getFileSystem().isMountPoint(f.getPath()));
			return;
		}
		default:
		}
		super.onPrepareDialog(id, dialog);
	}

	@Override
	protected Dialog onCreateDialog(int id) {
		LayoutInflater li = LayoutInflater.from(this);
		switch (id) {
		case Dialogs.DIALOG_PROPERTY:
			return Dialogs.createPropertyDialog(this, li);
		default:
		}
		return null;
	}


	protected void onError(Exception e) {
		Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show();
		e.printStackTrace();
	}

	
	@Override
	public boolean onContextItemSelected(MenuItem item) {
		if (contextFile == null) {
			return true;
		}
		File f = contextFile;
		//
		try {
			doContextMenu(item, f);
		} catch (IOException e) {
			onError(e);
		}
		return true;
	}

	private void doContextMenu(MenuItem item, File f) throws IOException {
		int id = item.getItemId();
		switch (id) {
		case R.id.file_context_menu_delete_id:
			perform(BinConstant.BIN_DELETE, f);
			break;
		case R.id.file_context_menu_rename_id:
			perform(BinConstant.BIN_RENAME, f);
			break;
		case R.id.file_context_menu_view_id:
			perform(BinConstant.BIN_VIEW, f);
			break;
		case R.id.file_context_menu_edit_id:
			perform(BinConstant.BIN_EDIT, f);
			break;
		case R.id.file_context_menu_property_id:
			showDialog(Dialogs.DIALOG_PROPERTY);
			break;
		}
	}

	@Override
	public void onCreateContextMenu(ContextMenu menu, View v,
			ContextMenuInfo menuInfo) {
		AdapterView.AdapterContextMenuInfo cmi = (AdapterView.AdapterContextMenuInfo) menuInfo;
		int pos = (cmi == null ? -1 : cmi.position);
		
		File f = getContextFile(pos);
		
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.file_context, menu);
		//
		boolean fnn = (f != null);
		boolean canRead = (fnn && f.canRead());
		boolean canWrite = (fnn && f.canWrite());
		boolean isFile = (fnn && f.isFile());
		boolean isFolder = (fnn && f.isDirectory());
		boolean isRoot = (fnn && f.isRoot());
		boolean isEmpty = (isFolder && f.isEmpty());
		boolean canEdit = (!isRoot && canWrite);

		contextFile = f;
		//
		//MenuItem send = menu.findItem(R.id.file_context_menu_send_id);
		//send.setEnabled(isFile && canRead);
		MenuItem prop = menu.findItem(R.id.file_context_menu_property_id);
		prop.setEnabled(fnn);
		MenuItem edit = menu.findItem(R.id.file_context_menu_edit_id);
		edit.setEnabled(canEdit && isFile);
		MenuItem view = menu.findItem(R.id.file_context_menu_view_id);
		view.setEnabled(canRead && (isFile)); //isFolder also for file managers?
		MenuItem rename = menu.findItem(R.id.file_context_menu_rename_id);
		rename.setEnabled(canEdit);
		MenuItem del = menu.findItem(R.id.file_context_menu_delete_id);
		del.setEnabled(canEdit && (isFile || isEmpty));
		//
		//not released
		rename.setVisible(false);
		rename.setEnabled(false);
		del.setVisible(false);
		del.setEnabled(false);
	}

	protected abstract File getContextFile(int pos);


	//private MenuItem newMenuItem;

	private MenuItem helpMenuItem;
	private MenuItem propertyMenuItem;


	@Override
	public boolean onPrepareOptionsMenu(Menu menu) {
		helpMenuItem.setEnabled(true);
		//
		File f = getSelectedFile();
		boolean fnn = (f != null);
		//boolean canWrite = (fnn && f.canWrite());
		//boolean isFolder = (fnn && f.isDirectory());
		//boolean isRoot = (fnn && f.isRoot());
		//
		propertyMenuItem.setEnabled(fnn);
		//boolean edit = (!isRoot && canWrite);
		//newMenuItem.setEnabled(edit && isFolder);
		//
		return true;
	}
	
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
//		case R.id.home_wallpaper_opt_menu_id:
//			AppHelper.startWallpaper(this);
//			return true;
//		case R.id.home_search_opt_menu_id:
//			doSearch();
//			return true;
		case R.id.home_help_opt_menu_id:
			AppHelper.help(this);
			return true;
		case R.id.home_property_opt_menu_id:
			showDialog(Dialogs.DIALOG_PROPERTY);
			return true;
		default:
			//
		}
		return super.onOptionsItemSelected(item);
	}

//	private void doSearch() {
//		//TODO
//		onSearchRequested();
//	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater mif = getMenuInflater();
		mif.inflate(R.menu.home_options, menu);
		//
		helpMenuItem = menu.findItem(R.id.home_help_opt_menu_id);
		propertyMenuItem = menu.findItem(R.id.home_property_opt_menu_id);
		//newMenuItem = menu.findItem(R.id.home_new_opt_menu_id);
		//
		Intent settings = AppHelper.createSettingsIntent(this);
		MenuItem mi = menu.findItem(R.id.home_settings_opt_menu_id);
		mi.setIntent(settings);
		//
		//
		//newMenuItem.setVisible(false);
		//newMenuItem.setEnabled(false);
		//
		return true;
	}

	protected abstract File getSelectedFile();
}
